//
//  GZLogItem.m
//  GZLogger
//
//  Created by GR on 2018/12/20.
//  Copyright © 2018 GR. All rights reserved.
//

#import "GZLogItem.h"
#import <execinfo.h>

@interface GZLogItem ()

@property (nonatomic, assign, readwrite) NSTimeInterval timestamp;

@property (nonatomic, copy, readwrite) NSString *file;
@property (nonatomic, assign, readwrite) NSUInteger line;
@property (nonatomic, copy, readwrite) NSString *function;

@property (nonatomic, assign, readwrite) GZLogLevel level;

@property (nonatomic, copy, readwrite) NSString *tag;
@property (nonatomic, copy, readwrite) NSString *content;

@property (nonatomic, assign, readwrite) NSUInteger stackLevel;
@property (nonatomic, copy, readwrite) NSString *stackSymbols;

@property (nonatomic, copy, readwrite) NSString *dataFileName;
@end

@implementation GZLogItem

- (NSString *)levelText {
    switch (self.level) {
        case GZLogLevelVerbose:
            return @"VERBOSE";
        case GZLogLevelInfo:
            return @"INFO";
        case GZLogLevelDebug:
            return @"DEBUG";
        case GZLogLevelWarning:
            return @"WARNING";
        case GZLogLevelError:
            return @"ERROR";
        case GZLogLevelFatal:
            return @"FATAL";
    }
}

- (NSDate *)time {
    return [NSDate dateWithTimeIntervalSince1970:self.timestamp];
}

- (NSString *)stackSymbols {
    if (self.stackLevel == 0) {
        return @"";
    }
    
    if (_stackSymbols.length == 0) {
        NSMutableString *symbols = [NSMutableString string];
        void *array = malloc(sizeof(void *) * (self.stackLevel + 5));
        int size = backtrace(array, (int)(self.stackLevel + 5));
        char **strings = backtrace_symbols(array, size);
        if (strings) {
            for (int i = 5; i < size; i++) {
                [symbols appendFormat:@"%s\n", strings[i]];
            }
            free(strings);
        }
        free(array);
        
        _stackSymbols = symbols;
    }
    return _stackSymbols;
}


+ (instancetype)itemWithTimestamp:(NSTimeInterval)timestamp
                             file:(NSString *)file
                             line:(NSUInteger)line
                         function:(NSString *)function
                            level:(GZLogLevel)level
                              tag:(NSString *)tag
                          content:(NSString *)content
                       stackLevel:(NSUInteger)stackLevel
                     dataFileName:(NSString *)dataFileName {
    
    GZLogItem *item     = [GZLogItem new];
    
    item.timestamp      = timestamp;
    item.file           = file.lastPathComponent;
    item.line           = line;
    item.function       = function;
    item.level          = level;
    item.tag            = tag;
    item.content        = content;
    item.stackLevel     = stackLevel;
    item.dataFileName   = dataFileName;
    
    return item;
}


@end
